home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
lib
/
clip.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-03
|
3KB
|
125 lines
/*
* @(#) clip.c 9.1 93/06/14 SCOINC
*
* Written by rr@sco.com 25-May-1993
* - performs clipping of line segments wrt a window in 2-D
*/
/*
* The Cohen-Sutherland clipping algorithm from pages 146-149 of the book
* "Fundamentals of Interactive Computer Graphics" by Foley and Van Dam.
* This algorithm is especially efficient when it is usually the case that
* the entire line segment to be drawn lies either inside or outside
* of the window (trivial acceptance or rejection). The algorithm relies on
* assigning each endpoint a four-bit code as follows :
*
* 1001 | 1000 | 1010
* ------|------|------
* 0001 | 0000 | 0010
* ------|------|------
* 0101 | 0100 | 0110
*
* with the center square above representing the window. I have altered the
* algorithm slightly to test for trivial acceptance first, followed by a
* check for trivial rejection (my most common case is trivial acceptance).
*
* The clipping routine is called clipline() and is called as follows :
*
* clipline(points, xmin, xmax, ymin, ymax);
* where points is an XSegment containing the two endpoints of the segment
* to be drawn, xmin and ymin represent the window minimums and xmax and ymax
* the window maximums. The clipline() routine returns an XSegment containing
* the endpoints of the clipped segment.
*/
#include <X11/Xlib.h>
reject_check(a, b)
int *a;
int *b;
{
static int i;
for (i=0;i<4;i++)
if (a[i] && b[i]) /*both endpts above, below, left, or right of window*/
return(1);
return(0);
}
accept_check(a, b)
int *a;
int *b;
{
static int i;
for (i=0; i<4; i++)
if (a[i] || b[i]) /* at least one endpoint not in window */
return(0);
return(1);
}
outcodes(x, y, xmin, xmax, ymin, ymax, out)
int x, y, xmin, xmax, ymin, ymax;
int *out;
{
out[0] = out[1] = out[2] = out[3] = 0;
if (y > ymax)
out[0] = 1;
if (y < ymin)
out[1] = 1;
if (x > xmax)
out[2] = 1;
if (x < xmin)
out[3] = 1;
}
XSegment
clipline(pts,xmin,xmax,ymin,ymax)
XSegment pts;
int xmin, xmax, ymin, ymax;
{
int outcode1[4], outcode2[4];
int accept, reject, done, tmp;
accept = reject = done = 0;
for(;;) {
outcodes(pts.x1, pts.y1, xmin, xmax, ymin, ymax, outcode1);
outcodes(pts.x2, pts.y2, xmin, xmax, ymin, ymax, outcode2);
accept = accept_check(outcode1, outcode2); /*check trivial accept*/
if (accept) done = 1;
else { /* first check trivial reject */
reject = reject_check(outcode1, outcode2); /*check trivial reject*/
if (reject) done = 1;
else { /* at most one endpoint is inside */
/* first, if P1 is inside window, exchange points 1 and 2 */
/* and their outcodes to guarantee that P1 is outside window */
if(!(outcode1[0] || outcode1[1] || outcode1[2] || outcode1[3])){
tmp = pts.x1; pts.x1 = pts.x2; pts.x2 = tmp;
tmp = pts.y1; pts.y1 = pts.y2; pts.y2 = tmp;
}
/* move P1 to the intersection point */
if (outcode1[0]) {
pts.x1=pts.x1+(pts.x2-pts.x1)*(ymax-pts.y1)/(pts.y2-pts.y1);
pts.y1 = ymax;
}
else if (outcode1[1]) {
pts.x1=pts.x1+(pts.x2-pts.x1)*(ymin-pts.y1)/(pts.y2-pts.y1);
pts.y1 = ymin;
}
else if (outcode1[2]) {
pts.y1=pts.y1+(pts.y2-pts.y1)*(xmax-pts.x1)/(pts.x2-pts.x1);
pts.x1 = xmax;
}
else if (outcode1[3]) {
pts.y1=pts.y1+(pts.y2-pts.y1)*(xmin-pts.x1)/(pts.x2-pts.x1);
pts.x1 = xmin;
}
}
}
if (done)
break;
}
return(pts);
}